#!/usr/bin/python3
# -*- coding: utf-8 -*-

from arrow import Arrow
from datetime import datetime
from os.path import isfile

from ikanda.core.callbacks import CallbackLogger
from ikanda.core.command import Environment, DownloadCommand
from ikanda.core.envnames import *
from ikanda.http import HttpResource


class JenkinsDownloadCommand(DownloadCommand):
    """ 使用Jenkins下载软件包的命令。

    """

    def __init__(
            self,
            src: str,
            dst: str,
            description: str = '',
            check_required: bool = False
    ):
        """
        构造使用Jenkins下载包的命令。

        :param src: 下载的源地址。
        :param dst: 下载的目标路径（本地路径）
        """
        super().__init__(src, dst, description, check_required)

    @staticmethod
    def __find_build(
            src: str,
            version_number: str,
            hr: HttpResource,
            callback: CallbackLogger
    ):
        callback.info('get all builds from {src}', src=src)
        rsp = hr.get_json(src, tree='builds[displayName,number,timestamp,url,artifacts[relativePath]]')

        builds = rsp['builds']
        if not builds:
            raise RuntimeError('no builds found')
        else:
            callback.success('found {n} build(s) in total', n=len(builds))

        return next(filter(lambda build_: str(build_['number']) == version_number, builds), None)

    @staticmethod
    def __find_last_successful_build(
            src: str,
            hr: HttpResource,
            callback: CallbackLogger
    ):
        callback.info('get last successful build from {src}', src=src)
        rsp = hr.get_json(src,
                          tree='lastSuccessfulBuild[displayName,number,timestamp,building,url,artifacts[relativePath]]')

        return rsp['lastSuccessfulBuild']

    def __call__(
            self,
            environment: Environment,
            resources: list,
            callback: CallbackLogger
    ):
        src = self.interpolate(self.src, environment)
        dst = self.abspath(self.interpolate(self.dst, environment), environment)
        version_number = environment.getstr(PKG_VERSION_NUMBER)

        hr: HttpResource = self.get_resource(HttpResource, resources)

        # 获取指定版本的下载地址。
        build = self.__find_build(src, version_number, hr, callback) if version_number \
            else self.__find_last_successful_build(src, hr, callback)

        # 执行下载。
        if build:
            display_name = build['displayName']
            timestamp_ = int(build['timestamp'])
            timestamp = Arrow.utcfromtimestamp(timestamp_ / 1000).to('local').datetime
            number = build['number']
            full_url = build['url'] + 'artifact/' + build['artifacts'][0]['relativePath']

            environment[PKG_DISPLAY_NAME] = display_name
            environment[PKG_TIMESTAMP] = timestamp
            environment[PKG_VERSION_NUMBER] = number

            callback.success(
                'found build[display-name={display_name},version-number={version_number},'
                'timestamp={timestamp},url={url}]',
                display_name=display_name, version_number=number, timestamp=timestamp, url=full_url)

            callback.info('download file from {url} as {dst}', url=full_url, dst=dst)

            hr.download(url=full_url, file=dst)

            if self.check_required:
                if not isfile(dst):
                    raise RuntimeError('cannot download file to ' + dst)
        else:
            raise RuntimeError('cannot find build[version-number=' + version_number + ']')
